﻿﻿using System.IO.Compression;

namespace DeviceCommons.DataHandling.Compression
{
    public class Compressor
    {
        public static byte[] Compress(ReadOnlySpan<byte> data)
        {
            return Compress(data.ToArray());
        }

        public byte[] Compress(byte[] data)
        {
            using var compressedStream = new MemoryStream();
            using (var gzipStream = new GZipStream(compressedStream, CompressionLevel.Optimal, leaveOpen: true))
            {
                gzipStream.Write(data, 0, data.Length);
                gzipStream.Flush(); // 确保数据被刷新
            } // GZipStream会在这里自动关闭并完成压缩
            return compressedStream.ToArray();
        }

        public byte[] Decompress(byte[] compressedData)
        {
            using (var compressedStream = new MemoryStream(compressedData))
            {
                using (var decompressedStream = new MemoryStream())
                {
                    using (var gzipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
                    {
                        gzipStream.CopyTo(decompressedStream);
                    }
                    return decompressedStream.ToArray();
                }
            }
        }

        public static async ValueTask<byte[]> CompressAsync(ReadOnlyMemory<byte> data, CancellationToken cancellationToken = default)
        {
            using var compressedStream = new MemoryStream();
            using (var gzipStream = new GZipStream(compressedStream, CompressionLevel.Optimal, true))
            {
                await gzipStream.WriteAsync(data, cancellationToken).ConfigureAwait(false);
                await gzipStream.FlushAsync(cancellationToken).ConfigureAwait(false);
            }
            return compressedStream.ToArray();
        }

        public static async ValueTask<byte[]> DecompressAsync(ReadOnlyMemory<byte> compressedData, CancellationToken cancellationToken = default)
        {
            using var compressedStream = new MemoryStream(compressedData.ToArray());
            using var decompressedStream = new MemoryStream();
            using (var gzipStream = new GZipStream(compressedStream, CompressionMode.Decompress, true))
            {
                await gzipStream.CopyToAsync(decompressedStream, cancellationToken).ConfigureAwait(false);
            }
            return decompressedStream.ToArray();
        }
    }
}
